#include <iostream>

// 继承
class Base{
// 父类中所有的非静态成员都会被子类继承下去
// 父类中的私有成员属性被编译器隐藏了，所以访问不到
public:
    int a;
protected:
    int b;
private:    //父类的私有权限成员子类没有权限访问
    int c;

public:
    static int s;

    Base(){
        a = 10;
        std::cout<< "Base 构造函数"<< std::endl;
    }
    ~Base(){
        std::cout<< "Base 析构函数"<< std::endl;
    }

    void func(){
        std::cout<< "Base func()"<< std::endl;
    }
    void func(int a){
        std::cout<< "Base func(int a)"<< std::endl;
    }
};

// 先构造父类，在构造子类，析构顺序相反
class son : public Base{
public:
    int a;
    static int s;
    son(){
        std::cout<< "son 构造函数"<< std::endl;
        a = 10;
    }
    ~son(){
        std::cout<< "son 析构函数"<< std::endl;
    }

    void func(){
        std::cout<< "son func()"<< std::endl;
    }
};

// 公有继承：成员的属性与父类的相比没有变化
class son1 : public Base{
    void func(){
        a = 10; // 父类中的公共权限成员，到子类中依旧是公共权限
        b = 10; // 父类中的保护权限成员，到子类中依旧是保护权限
        // c = 10; // 父类中的私有权限成员，子类访问不到
    }

};

// 保护继承：父类中的公共权限成员和保护权限成员继承过来后，都会变成保护权限成员
class son2 : protected Base{
    void func(){
        a = 10; // 父类中的私有权限成员，到子类中变为保护成员
        b = 10; // 父类中的私有权限成员，到子类中变为保护成员
        // c = 10; // 父类中的私有权限成员，子类访问不到
    }
};

// 私有继承：父类中的公共权限成员和保护权限成员继承过来后，都会变成私有权限成员
class son3 : private Base{
    void func(){
        a = 10; // 父类中的公共权限成员，到子类中变为私有成员
        b = 10; // 父类中的私有权限成员，到子类中变为私有成员
        // c = 10; // 父类中的私有权限成员，子类访问不到
    }
};

// 多继承: 一个类可以继承多个类
// c++项目中基本不使用多继承
// 菱形继承问题:当两个父类拥有相同数据时,需要用作用域加以区分
// 菱形继承导致数据有两份,资源浪费
// 解决方案:虚继承  virtual
// 添加virtual之后从父类继承过来的不是数据,而是一个虚基类指针vbptr,通过偏移量来找到同一个数据
class animal{
public:
    int age;
};
class spider: public virtual animal {};
class man: public virtual animal {};
class spiderman : public spider , public man {};


void test(){
    // son1 s1;
    // s1.a = 100;
    // s1.b = 100;  // 在son1中，b是保护权限，因此访问不到

    // son2 s2;
    // s2.a = 100;   // 在son2中，a是保护权限，因此访问不到

    // son3 s3;
    // s2.a = 100;   // 在son3中，a是私有权限，因此访问不到

// 同名成员处理
    son s ;
    // 直接访问成员变量，用的是子类中的成员
    std::cout<< "son a:"<< s.a << std::endl;
    // 想访问父类中成员变量，需要加作用域
    std::cout<< "base a:"<< s.Base::a << std::endl;
    // 直接访问成员函数, 用的是子类中的成员
    s.func();
// 如果子类和父类中同时存在同名的成员函数，子类的同名成员会隐藏掉父类中所有同名成员函数
// 如果想访问到父类中隐藏的成员函数，需要加作用域
    s.Base::func();
    s.Base::func(100);
// 同名静态成员处理 与同名成员处理基本一致

// 多继承同名
    spiderman peter;
    
    peter.spider::age = 10;     
    peter.man::age = 20;     
    std::cout<< peter.age << std::endl;

}

int main()
{
    test();
    return 0;
}
